package top.chukongxiang.monitorservice.tools.rtp;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ByteUtil;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.nio.ByteOrder;
import java.util.Optional;

/**
 * @author 楚孔响
 * @version 1.0
 * @date 2023/9/18 19:51
 */
@Slf4j
public class PsmWrapper {

    @Getter
    private final byte[] data;

    private Integer programStreamInfoLength;
    private Integer elementStreamMapLength;
    private byte[] elementStreamMap;
    private Byte videoStreamType;
    private Byte audioStreamType;

    public PsmWrapper(byte[] psmHeader) {
        this.data = psmHeader;
    }

    public int getProgramStreamInfoLength() {
        if (this.programStreamInfoLength != null) {
            return this.programStreamInfoLength;
        }
        this.programStreamInfoLength = Short.toUnsignedInt( ByteUtil.bytesToShort(data, 8, ByteOrder.BIG_ENDIAN) );
        return this.programStreamInfoLength;
    }

    public int getElementStreamMapLength() {
        if (this.elementStreamMapLength != null) {
            return this.elementStreamMapLength;
        }
        int programStreamInfoLength = getProgramStreamInfoLength();
        this.elementStreamMapLength = Short.toUnsignedInt(ByteUtil.bytesToShort(data, 8 + programStreamInfoLength + 2, ByteOrder.BIG_ENDIAN));
        return this.elementStreamMapLength;
    }

    public byte[] getElementStreamMap() {
        if (this.elementStreamMap != null) {
            return this.elementStreamMap;
        }
        int programStreamInfoLength = getProgramStreamInfoLength();
        int elementStreamMapLength = getElementStreamMapLength();
        this.elementStreamMap = ArrayUtil.sub(data, 8 + programStreamInfoLength + 4, 8 + programStreamInfoLength + 4 + elementStreamMapLength);
        return this.elementStreamMap;
    }

    public Optional<Byte> getVideoStreamType() {
        if (this.videoStreamType != null) {
            return Optional.of(this.videoStreamType);
        }
        byte[] elementStreamMap = getElementStreamMap();
        for (int i = 0; i < elementStreamMap.length; i += 4) {
            if (elementStreamMap[i + 1] == (byte) 0xE0) {
                this.videoStreamType = elementStreamMap[i];
                return Optional.of(this.videoStreamType);
            }
        }
        return Optional.empty();
    }

    public Optional<Byte> getAudioStreamType() {
        if (this.audioStreamType != null) {
            return Optional.of(this.audioStreamType);
        }
        byte[] elementStreamMap = getElementStreamMap();
        for (int i = 0; i < elementStreamMap.length; i += 4) {
            if (elementStreamMap[i + 1] == (byte) 0xC0) {
                this.audioStreamType = elementStreamMap[i];
                return Optional.of(this.audioStreamType);
            }
        }
        return Optional.empty();
    }

}
